package com.tanhua.app.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.app.exception.BusinessException;
import com.tanhua.app.exception.ErrorResult;
import com.tanhua.app.interceptor.UserHolder;
import com.tanhua.commons.utils.Constants;
import com.tanhua.config.template.OssTemplate;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.pojo.UserInfo;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VisitorsVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class MovementService {
    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;
    
    @Autowired
    private StringRedisTemplate redisTemplate;

    @DubboReference
    private VisitorsApi visitorsApi;

    @Autowired
    private UserFreezeService userFreezeService;

    @Autowired
    private MqMessageService mqMessageService;

    //发布动态
    public void sendmovements(Movement movement, MultipartFile[] imageContent) throws IOException {
        //判断用户是否被冻结
        userFreezeService.freezeCheck(UserHolder.getUserId(),"3");
        //1.判断发布的动态是否存在
        if (StringUtils.isEmpty(movement.getTextContent())){
            throw new BusinessException(ErrorResult.contentError());
        }
        //2.获取当前登录的用户id
        Long userId = UserHolder.getUserId();
        //3.将文件上传到阿里云oss,获取请求地址
        List<String> medias = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            medias.add(upload);
        }
        //4.将数据封装到Movement对象中
        movement.setUserId(userId);
        movement.setMedias(medias);
        //5.调用api发送动态
        String movementId = movementApi.publish(movement);
        //6.发送动态审核消息
        mqMessageService.sendAudiMessage(movementId);
    }

    //查询个人动态
    public PageResult<MovementsVo> findByUserId(Long userId, Integer page, Integer pageSize) {
        //判断userId是否为空,如果为空,则使用当前登录的id
        if (userId == null){
            userId = UserHolder.getUserId();
        }
        //根据userid查询动态
        PageResult<Movement> movementPr = movementApi.findPageByUserId(userId,page,pageSize);
        //判断动态数据是否为空,如果为空,直接返回
        if (movementPr.getItems() == null ||  movementPr.getItems().isEmpty()) {
            return new PageResult<>(movementPr.getPage(), movementPr.getPagesize(),0,null);
        }
        //根据用户id查询用户详情
        UserInfo userInfo = userInfoApi.findById(userId);
        //遍历多个动态封装vo数据
        List<Movement> list = movementPr.getItems();
        List<MovementsVo> vo = new ArrayList<>();
        for (Movement movement : list) {
            MovementsVo movementsVo = MovementsVo.init(userInfo,movement);
            vo.add(movementsVo);
        }
        //返回结果
        return new PageResult<>(movementPr.getPage(),movementPr.getPagesize(),movementPr.getCounts(),vo);
    }

    //查询好友动态
    public PageResult<MovementsVo> findFriendsMovements(Integer page, Integer pageSize) {
        //1.查询动态信息并判断是否为空
        List<Movement> movementList = movementApi.findFriendsMovements(UserHolder.getUserId(),page, pageSize);
        return getPageResult(page, pageSize, movementList);
    }

    //封装分页查询对象
    private PageResult getPageResult(Integer page, Integer pageSize, List<Movement> movementList) {
        if (CollUtil.isEmpty(movementList)){
            //return new PageResult<>(page,pageSize,0,null);
        }
        //2.获取发布动态的用户ids
        List<Long> ids = movementList.stream().map(Movement::getUserId).collect(Collectors.toList());
        //3.根据ids查询动态发布者的详细信息
        List<UserInfo> userInfoList = userInfoApi.findByIds(ids);
        Map<Long, UserInfo> userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, Function.identity()));
        //4.将动态信息和动态发布者详细信息封装到vo中
        List<MovementsVo> vos = new ArrayList<>();

        for (Movement movement : movementList) {
            UserInfo userInfo = userInfoMap.get(movement.getUserId());
            if (userInfo != null) {
                MovementsVo movementsVo = MovementsVo.init(userInfo, movement);


                //让点赞可以正常回显 需要给hasliked赋值
                String key = Constants.MOVEMENTS_INTERACT_KEY+movement.getId().toHexString();
                String likeKey = Constants.MOVEMENT_LIKE_HASHKEY+UserHolder.getUserId();
                if (redisTemplate.opsForHash().hasKey(key,likeKey)){
                    //如果redis中有数据则已经点赞
                    movementsVo.setHasLiked(1);
                }else {
                    movementsVo.setHasLiked(0);
                }

                //让喜欢可以正常回显 需要给hasloved赋值
                String loveKey = Constants.MOVEMENT_LOVE_HASHKEY+UserHolder.getUserId();
                if (redisTemplate.opsForHash().hasKey(key,loveKey)){
                    //如果redis中有数据则已经点赞
                    movementsVo.setHasLoved(1);
                }else {
                    movementsVo.setHasLoved(0);
                }
                vos.add(movementsVo);
            }
        }
        //返回结果
        return new PageResult(page, pageSize,0,vos);
    }

    //推荐动态
    public PageResult recommend(Integer page, Integer pagesize) {
        //redis存取推荐信息是 "MOVEMENTS_RECOMMEND_"+用户id
        String redisKey = Constants.MOVEMENTS_RECOMMEND+UserHolder.getUserId();
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        //判断redis中是否有推荐的pid列表 如果没有则随机调用api获取十条动态
        List<Movement> movementList = new ArrayList<>();
        if (StringUtils.isBlank(redisValue)){
            movementList = movementApi.randomMovements(10);
        }else {
            //如果存在 则根据pid查询动态数据,先把redis中的数据切割成字符数组 再把数组进行分页 ,再调用api查询动态数据
            String[] pidArr = redisValue.split(",");
            //判断当前页是否有数据
            if (pidArr.length>(page-1)*pagesize){
                List<Long> pids = Arrays.stream(pidArr)
                        .skip((page - 1) * pagesize)//跳过哪些数据
                        .limit(pagesize)            //分页显示哪些数据
                        .map(pid -> Long.parseLong(pid))//将pid由String转为Long类型
                        .collect(Collectors.toList());//将流转换为list集合输出
                movementList = movementApi.getMovementsByPid(pids);
            }

        }

        //构建vo对线并赋值 返回pageresult结果
        return getPageResult(page,pagesize,movementList);
    }

    //根据动态id查询动态信息
    public MovementsVo findById(String movementId) {
        //根据动态id查询动态信息
        Movement movement = movementApi.findById(movementId);
        if (movement == null) {
            return null;
        }
        //根据动态中的userId查询用户信息
        UserInfo userInfo = userInfoApi.findById(movement.getUserId());
        //封装到vo对象
        MovementsVo vo = MovementsVo.init(userInfo,movement);

        //发送日志消息
        mqMessageService.sendLogMessage(UserHolder.getUserId(),"0202","movement",movementId);

        return vo;
    }

    //查看访问记录
    public List<VisitorsVo> visitors(Long userId) {
        //在radis中查询访问时间
        String key = Constants.VISITORS_USER;
        String userIdKey = String.valueOf(userId);
        String value = (String) redisTemplate.opsForHash().get(key, userIdKey);
        Long date = StringUtils.isEmpty(value) ? null : Long.valueOf(value);
        //根据userId查询访问者ids
        List<Visitors> visitorsList = visitorsApi.find(userId,date);
        if (CollUtil.isEmpty(visitorsList)){
            return null;
        }
        List<Long> ids = visitorsList.stream().map(Visitors::getVisitorUserId).collect(Collectors.toList());
        //根据ids查询访问者详细信息
        List<UserInfo> userInfoList = userInfoApi.findByIds(ids);
        Map<Long, UserInfo> userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, Function.identity()));
        //封装到vo对象中
        List<VisitorsVo> vos = new ArrayList<>();
        for (Visitors visitors : visitorsList) {
            UserInfo userInfo = userInfoMap.get(visitors.getVisitorUserId());
            VisitorsVo vo = VisitorsVo.init(userInfo,visitors);
            vos.add(vo);
        }
        return vos;
    }
}
